package com.qf.aspect;

import com.qf.annotation.Log;
import com.qf.entity.SysLog;
import com.qf.mapper.SysLogMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;


/**
 *日志切面,解析日志注解,解析日志注解,插入日志信息
 *
 */
@Aspect//Aop技术,切面
@Component//ioc技术,帮造对象
public class LogAspect {
    /*
    增强方法,前置,后置,环绕,后置返回,后置异常通知
    *使用后置记录日志
     */
    @Autowired
    private SysLogMapper logManagerr;
    @After("@annotation(com.qf.annotation.Log)")//annotation=切入的目标是日志注解
    public void recordLog(JoinPoint joinPoint){
        SysLog sysLog = new SysLog();
        // 设置当前时间（精确到秒）
        sysLog.setLogTime(LocalDateTime.now());
        // 获得当前请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // ip
        // ip
        String ip = getIpAddress(request);
        //请求方法
        String method = request.getMethod();
        sysLog.setIp(ip);
        sysLog.setMethod(method);
        sysLog.setUsername(new String("admin"));
        //解析注解
        HashMap<String, String> map = getAnnoLog(joinPoint);
        for (String key : map.keySet()) {
            System.out.println("Key: " + key + ", Value: " + map.get(key));
        }
        sysLog.setType(map.get("type"));
        sysLog.setLog(map.get("log"));
        logManagerr.insertLog( sysLog );
    }
    /**
     * 获得访问者ip地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 封装的方法,通过反射技术获得目标方法上的注解的值
     */
    public static HashMap<String, String> getAnnoLog(JoinPoint joinPoint) {
        HashMap<String, String> map = new HashMap<>( );
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature( );
            // 获得目标方法对象
            Method method = signature.getMethod( );
            // 获得目标方法对象上的日志注解
            Log myLog = method.getDeclaredAnnotation(Log.class);
            // 获得日志注解上的值
            String log = myLog.value( );
            String type = myLog.type( );

            map.put("log", log);
            map.put("type", type);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return map;
    }

}
